import { 
  DeviceInfo, 
  RegisteredDevice, 
  DeviceType, 
  DeviceCapabilities,
  SmartInputError,
  LogEntry,
  LogLevel 
} from '../types';
import { config, logConfig } from '../config';
import DataPersistence from './DataPersistence';
import { WebSocketService } from './WebSocketService';
import { SSEService } from './SSEService';
import PairingManager from './PairingManager';

class DeviceManager {
  private devices: Map<string, RegisteredDevice> = new Map();
  private socketToDevice: Map<string, string> = new Map();
  private cleanupInterval: NodeJS.Timeout;
  private dataPersistence: DataPersistence;
  private autoSaveInterval: NodeJS.Timeout;
  private deviceIdCounter: number = 0; // 用于生成唯一ID
  private fingerprintToDeviceId: Map<string, string> = new Map(); // 新增指纹-Id映射
  private wsService?: WebSocketService;
  private sseService?: SSEService;
  private pairingManager?: PairingManager;

  setWebSocketService(ws: WebSocketService) {
    this.wsService = ws;
  }
  setSSEService(sse: SSEService) {
    this.sseService = sse;
  }
  setPairingManager(pairingManager: PairingManager) {
    this.pairingManager = pairingManager;
  }

  constructor() {
    // 初始化数据持久化
    this.dataPersistence = new DataPersistence();
    
    // 加载持久化数据
    this.loadPersistedData();
    
    // 初始化设备ID计数器
    this.initializeDeviceIdCounter();
    
    // 定期清理离线设备
    this.cleanupInterval = setInterval(() => {
      this.cleanupOfflineDevices();
    }, config.cleanup.deviceTimeout);
    
    // 定期自动保存（每2分钟）
    this.autoSaveInterval = setInterval(() => {
      this.savePersistedData();
    }, 2 * 60 * 1000);
  }

  /**
   * 初始化设备ID计数器
   */
  private initializeDeviceIdCounter(): void {
    // 从现有设备中找出最大的数字ID
    let maxId = 0;
    for (const [deviceId] of this.devices) {
      const match = deviceId.match(/^[a-z]+_([a-z0-9]+)_(\d+)$/);
      if (match && match[2]) {
        const numId = parseInt(match[2], 10);
        if (numId > maxId) {
          maxId = numId;
        }
      }
    }
    this.deviceIdCounter = maxId + 1;
    this.log('info', `设备ID计数器初始化: ${this.deviceIdCounter}`);
  }

  /**
   * 生成唯一的设备ID
   */
  generateUniqueDeviceId(deviceType: DeviceType, hardwareFingerprint?: string): string {
    const timestamp = Date.now();
    const counter = this.deviceIdCounter++;
    
    // 基于设备类型和硬件指纹生成ID
    if (hardwareFingerprint) {
      // 使用硬件指纹生成稳定的ID
      const fingerprintHash = this.generateFingerprintHash(hardwareFingerprint);
      return `${deviceType}_${fingerprintHash}_${counter}`;
    } else {
      // 备用方案：使用时间戳和计数器
      return `${deviceType}_${timestamp}_${counter}`;
    }
  }

  /**
   * 生成硬件指纹哈希
   */
  private generateFingerprintHash(fingerprint: string): string {
    // 简单的哈希算法，实际项目中可以使用更安全的哈希
    let hash = 0;
    for (let i = 0; i < fingerprint.length; i++) {
      const char = fingerprint.charCodeAt(i);
      hash = ((hash << 5) - hash) + char;
      hash = hash & hash; // 转换为32位整数
    }
    return Math.abs(hash).toString(36).substring(0, 8);
  }

  /**
   * 根据硬件指纹查找或生成设备ID
   */
  findOrGenerateDeviceId(deviceType: DeviceType, hardwareFingerprint?: string): string {
    if (hardwareFingerprint) {
      // 优先查永久映射表
      const existingDeviceId = this.findDeviceByFingerprint(hardwareFingerprint);
      if (existingDeviceId) {
        this.log('info', `根据硬件指纹找到现有设备: ${existingDeviceId}`);
        return existingDeviceId;
      }
    }
    // 生成新的唯一ID
    const newDeviceId = this.generateUniqueDeviceId(deviceType, hardwareFingerprint);
    // 新生成时写入永久映射表
    if (hardwareFingerprint) {
      this.fingerprintToDeviceId.set(hardwareFingerprint, newDeviceId);
    }
    this.log('info', `生成新的设备ID: ${newDeviceId}`);
    return newDeviceId;
  }

  /**
   * 根据硬件指纹查找设备（严格等于）
   */
  private findDeviceByFingerprint(hardwareFingerprint: string): string | null {
    // 优先查永久映射表
    if (this.fingerprintToDeviceId.has(hardwareFingerprint)) {
      return this.fingerprintToDeviceId.get(hardwareFingerprint)!;
    }
    // 兼容老逻辑
    for (const [deviceId, device] of this.devices) {
      if (device.hardwareFingerprint && device.hardwareFingerprint === hardwareFingerprint) {
        // 自动补建映射
        this.fingerprintToDeviceId.set(hardwareFingerprint, deviceId);
        return deviceId;
      }
    }
    return null;
  }

  /**
   * 注册新设备（服务端生成ID，确保唯一）
   */
  registerDeviceWithServerGeneratedId(
    socketId: string,
    deviceInfo: Omit<DeviceInfo, 'id' | 'timestamp'> & { hardwareFingerprint?: string }
  ): RegisteredDevice {
    try {
      // 确保设备名称不为空
      const normalizedDeviceInfo = {
        ...deviceInfo,
        name: deviceInfo.name && deviceInfo.name.trim() ? deviceInfo.name : this.generateDefaultDeviceName(deviceInfo.type),
        capabilities: this.normalizeDeviceCapabilities(deviceInfo.type, deviceInfo.capabilities)
      };
      // 先查找是否已存在该指纹的设备
      const deviceId = this.findOrGenerateDeviceId(normalizedDeviceInfo.type, normalizedDeviceInfo.hardwareFingerprint);
      if (this.devices.has(deviceId)) {
        const existingDevice = this.devices.get(deviceId)!;
        // 更新socketId和在线状态
        existingDevice.socketId = socketId;
        existingDevice.isOnline = true;
        existingDevice.lastSeen = Date.now();
        this.socketToDevice.set(socketId, deviceId);
        this.log('info', `复用已存在设备: ${deviceId}`);
        return existingDevice;
      }
      // 不存在则新注册
      return this.registerDeviceWithId(socketId, deviceId, normalizedDeviceInfo);
    } catch (error) {
      this.log('error', `设备注册失败: ${error instanceof Error ? error.message : 'Unknown error'}`, {
        socketId,
        deviceInfo
      });
      throw error;
    }
  }

  /**
   * 标准化设备能力配置
   */
  private normalizeDeviceCapabilities(deviceType: DeviceType, capabilities?: any): DeviceCapabilities {
    const defaultCapabilities = this.getDefaultCapabilities(deviceType);
    
    if (!capabilities || typeof capabilities !== 'object') {
      return defaultCapabilities;
    }
    
    // 合并客户端提供的能力和默认能力
    return {
      ...defaultCapabilities,
      ...capabilities
    };
  }

  /**
   * 获取默认设备能力配置
   */
  private getDefaultCapabilities(deviceType: DeviceType): DeviceCapabilities {
    switch (deviceType) {
      case 'mobile':
        return {
          canSendVoice: true,
          canReceiveText: false,
          canGenerateQR: false,
          canScanQR: true
        };
      case 'browser':
        return {
          canSendVoice: false,
          canReceiveText: true,
          canGenerateQR: true,
          canScanQR: false
        };
      case 'desktop':
        return {
          canSendVoice: true,
          canReceiveText: true,
          canGenerateQR: true,
          canScanQR: true
        };
      default:
        return {
          canSendVoice: false,
          canReceiveText: false,
          canGenerateQR: false,
          canScanQR: false
        };
    }
  }

  /**
   * 生成默认设备名称
   */
  private generateDefaultDeviceName(deviceType: DeviceType): string {
    const timestamp = Date.now();
    const random = Math.random().toString(36).substring(2, 6);
    
    switch (deviceType) {
      case 'mobile':
        return `Mobile Device ${random}`;
      case 'browser':
        return `Browser ${random}`;
      case 'desktop':
        return `Desktop ${random}`;
      default:
        return `Device ${random}`;
    }
  }

  /**
   * 手动注册设备（使用指定的设备ID）
   */
  registerDeviceWithId(
    socketId: string,
    deviceId: string,
    deviceInfo: Omit<DeviceInfo, 'id' | 'timestamp'>
  ): RegisteredDevice {
    try {
      const timestamp = Date.now();
      const registeredDevice: RegisteredDevice = {
        ...deviceInfo,
        id: deviceId,
        timestamp,
        socketId,
        lastSeen: timestamp,
        isOnline: true
      };
      this.validateDeviceInfo(registeredDevice);
      if (deviceInfo.type === 'browser') {
        this.handleBrowserInstanceUniqueness(deviceId, socketId);
      }
      if (this.devices.has(deviceId)) {
        const existingDevice = this.devices.get(deviceId)!;
        registeredDevice.timestamp = existingDevice.timestamp;
      }
      this.devices.set(deviceId, registeredDevice);
      this.socketToDevice.set(socketId, deviceId);
      this.log('info', `设备注册成功: ${deviceInfo.type} - ${deviceInfo.name} (${deviceId})`, {
        deviceId,
        socketId,
        deviceType: deviceInfo.type
      });
      return registeredDevice;
    } catch (error) {
      this.log('error', `设备注册失败: ${error instanceof Error ? error.message : 'Unknown error'}`, {
        socketId,
        deviceInfo
      });
      throw error;
    }
  }

  /**
   * 注册新设备（兼容旧版本，但优先使用服务端生成ID）
   */
  registerDevice(
    socketId: string,
    deviceInfo: Omit<DeviceInfo, 'id' | 'timestamp'> & { deviceId?: string; hardwareFingerprint?: string }
  ): RegisteredDevice {
    // 确保设备名称和能力配置正确
    const normalizedDeviceInfo = {
      ...deviceInfo,
      name: deviceInfo.name && deviceInfo.name.trim() ? deviceInfo.name : this.generateDefaultDeviceName(deviceInfo.type),
      capabilities: this.normalizeDeviceCapabilities(deviceInfo.type, deviceInfo.capabilities)
    };
    
    // 如果客户端提供了deviceId，检查是否可用
    if (normalizedDeviceInfo.deviceId && !this.devices.has(normalizedDeviceInfo.deviceId)) {
      // 客户端ID可用，使用客户端ID
      return this.registerDeviceWithId(socketId, normalizedDeviceInfo.deviceId, normalizedDeviceInfo);
    } else {
      // 使用服务端生成ID
      return this.registerDeviceWithServerGeneratedId(socketId, normalizedDeviceInfo);
    }
  }

  /**
   * 处理浏览器实例唯一性
   */
  private handleBrowserInstanceUniqueness(deviceId: string, socketId: string): void {
    const baseBrowserId = this.extractBaseBrowserId(deviceId);
    
    if (!baseBrowserId) {
      // 无法识别浏览器基础ID，跳过唯一性检查
      return;
    }

    const duplicateDevices: string[] = [];
    
    // 查找相同浏览器的其他实例
    for (const [existingDeviceId, device] of this.devices) {
      if (existingDeviceId !== deviceId && device.type === 'browser') {
        const existingBaseBrowserId = this.extractBaseBrowserId(existingDeviceId);
        if (existingBaseBrowserId === baseBrowserId) {
          duplicateDevices.push(existingDeviceId);
        }
      }
    }

    // 清理重复的设备实例
    duplicateDevices.forEach(duplicateDeviceId => {
      const duplicateDevice = this.devices.get(duplicateDeviceId);
      if (duplicateDevice) {
        // 标记为离线
        duplicateDevice.isOnline = false;
        duplicateDevice.lastSeen = Date.now();
        
        // 清理socket映射
        this.socketToDevice.delete(duplicateDevice.socketId);
        
        this.log('info', `浏览器实例合并: 停用重复设备 ${duplicateDeviceId}`, {
          newDeviceId: deviceId,
          newSocketId: socketId,
          duplicateDeviceId,
          duplicateSocketId: duplicateDevice.socketId
        });
      }
    });

    if (duplicateDevices.length > 0) {
      this.log('info', `浏览器唯一性控制: 为设备 ${deviceId} 清理了 ${duplicateDevices.length} 个重复实例`);
    }
  }

  /**
   * 从设备ID中提取浏览器基础标识
   */
  private extractBaseBrowserId(deviceId: string): string | null {
    try {
      // 对于基于指纹的ID: browser_chrome_abc123def456
      const match = deviceId.match(/^browser_chrome_([a-z0-9]{12})$/);
      if (match && match[1]) {
        return match[1]; // 返回浏览器指纹ID
      }
      
      // 对于时间戳+随机数的旧格式，无法确定唯一性
      return null;
    } catch (error) {
      return null;
    }
  }

  /**
   * 注销设备
   */
  unregisterDevice(socketId: string): boolean {
    const deviceId = this.socketToDevice.get(socketId);
    if (!deviceId) {
      return false;
    }

    const device = this.devices.get(deviceId);
    if (device) {
      // 只更新 lastSeen，不立即 isOnline=false
      device.lastSeen = Date.now();
      // 不再直接失效配对，由 PairingManager 定时任务处理
      this.log('info', `注销设备: ${device.type} - ${device.name} (${deviceId})`, {
        deviceId,
        socketId,
        deviceType: device.type
      });
    }

    this.socketToDevice.delete(socketId);
    return true;
  }

  /**
   * 获取设备信息
   */
  getDevice(deviceId: string): RegisteredDevice | undefined {
    return this.devices.get(deviceId);
  }

  /**
   * 通过Socket ID获取设备
   */
  getDeviceBySocketId(socketId: string): RegisteredDevice | undefined {
    const deviceId = this.socketToDevice.get(socketId);
    return deviceId ? this.devices.get(deviceId) : undefined;
  }

  /**
   * 获取所有在线设备
   */
  getOnlineDevices(): RegisteredDevice[] {
    return Array.from(this.devices.values()).filter(device => device.isOnline);
  }

  /**
   * 获取所有设备
   */
  getAllDevices(): RegisteredDevice[] {
    return Array.from(this.devices.values());
  }

  /**
   * 获取特定类型的设备
   */
  getDevicesByType(type: DeviceType): RegisteredDevice[] {
    return Array.from(this.devices.values()).filter(device => device.type === type);
  }

  /**
   * 获取具有特定能力的设备
   */
  getDevicesByCapability(capability: keyof DeviceCapabilities): RegisteredDevice[] {
    return Array.from(this.devices.values()).filter(device => device.capabilities[capability]);
  }

  /**
   * 更新设备最后活跃时间
   */
  updateDeviceActivity(deviceId: string): void {
    const device = this.devices.get(deviceId);
    if (device) {
      device.lastSeen = Date.now();
      // 自动恢复配对关系：如果有配对管理器，尝试恢复失效配对
      if (this.pairingManager) {
        this.pairingManager.tryRestorePairingsForDevice(deviceId);
      }
    }
  }

  /**
   * 检查设备是否在线（优先查socket连接池，兜底用lastSeen）
   */
  isDeviceOnline(deviceId: string): boolean {
    const device = this.devices.get(deviceId);
    if (!device) return false;
    // 优先查WebSocket连接池
    if (this.wsService && this.wsService.hasConnection(deviceId)) {
      return true;
    }
    // 查SSE连接池
    if (this.sseService && this.sseService.getDeviceConnections(deviceId).length > 0) {
      return true;
    }
    // 兜底：lastSeen宽限期
    const now = Date.now();
    const timeout = config.cleanup.deviceTimeout || 5 * 60 * 1000; // 5分钟
    return (now - device.lastSeen) < timeout;
  }

  /**
   * 获取设备统计信息
   */
  getStats() {
    const allDevices = this.getAllDevices();
    const onlineDevices = this.getOnlineDevices();

    return {
      totalDevices: allDevices.length,
      onlineDevices: onlineDevices.length,
      devicesByType: {
        mobile: allDevices.filter(d => d.type === 'mobile').length,
        browser: allDevices.filter(d => d.type === 'browser').length,
        desktop: allDevices.filter(d => d.type === 'desktop').length
      },
      onlineByType: {
        mobile: onlineDevices.filter(d => d.type === 'mobile').length,
        browser: onlineDevices.filter(d => d.type === 'browser').length,
        desktop: onlineDevices.filter(d => d.type === 'desktop').length
      }
    };
  }

  /**
   * 获取设备数量 (兼容方法)
   */
  getDeviceCount(): number {
    return this.getOnlineDevices().length;
  }

  /**
   * 获取设备状态统计 (兼容方法)
   */
  getDevicesStatus() {
    const devices = this.getAllDevices();
    const onlineDevices = this.getOnlineDevices();

    return {
      total: devices.length,
      online: onlineDevices.length,
      byType: {
        mobile: devices.filter(d => d.type === 'mobile').length,
        browser: devices.filter(d => d.type === 'browser').length,
        desktop: devices.filter(d => d.type === 'desktop').length
      },
      onlineByType: {
        mobile: onlineDevices.filter(d => d.type === 'mobile').length,
        browser: onlineDevices.filter(d => d.type === 'browser').length,
        desktop: onlineDevices.filter(d => d.type === 'desktop').length
      },
      sessions: 0 // 暂时设为0，因为当前实现中没有会话概念
    };
  }

  /**
   * 清理离线设备（只有 lastSeen 超过宽限期才设为 isOnline=false 并物理删除）
   */
  private cleanupOfflineDevices(): void {
    const now = Date.now();
    const timeout = config.cleanup.deviceTimeout || 5 * 60 * 1000;
    let cleanedCount = 0;

    for (const [deviceId, device] of this.devices.entries()) {
      if ((now - device.lastSeen) > timeout) {
        device.isOnline = false; // 超时才真正设为离线
        this.devices.delete(deviceId);
        cleanedCount++;
        if (logConfig.level === 'debug') {
          this.log('debug', `清理离线设备: ${device.type} - ${device.name} (${deviceId})`, {
            deviceId,
            lastSeen: device.lastSeen,
            offlineTime: now - device.lastSeen
          });
        }
      }
    }

    if (cleanedCount > 0) {
      this.log('info', `清理了 ${cleanedCount} 个离线设备`);
    }
  }

  /**
   * 验证设备信息
   */
  validateDeviceInfo(device: RegisteredDevice): void {
    if (!device.id || typeof device.id !== 'string') {
      throw new SmartInputError('Invalid device ID', 'INVALID_DEVICE_ID', 400);
    }

    if (!device.type || !['mobile', 'browser', 'desktop'].includes(device.type)) {
      throw new SmartInputError('Invalid device type', 'INVALID_DEVICE_TYPE', 400);
    }

    if (!device.name || typeof device.name !== 'string' || device.name.trim().length === 0) {
      throw new SmartInputError('Invalid device name', 'INVALID_DEVICE_NAME', 400);
    }

    if (!device.capabilities || typeof device.capabilities !== 'object') {
      throw new SmartInputError('Invalid device capabilities', 'INVALID_CAPABILITIES', 400);
    }

    // 验证能力配置的合理性
    const { capabilities } = device;
    if (device.type === 'mobile' && !capabilities.canSendVoice) {
      throw new SmartInputError('Mobile devices must support voice sending', 'INVALID_MOBILE_CAPABILITIES', 400);
    }

    if (device.type === 'browser' && !capabilities.canReceiveText) {
      throw new SmartInputError('Browser devices must support text receiving', 'INVALID_BROWSER_CAPABILITIES', 400);
    }
  }

  /**
   * 日志记录
   */
  private log(level: LogLevel, message: string, metadata?: Record<string, any>): void {
    const logEntry: LogEntry = {
      level,
      message,
      timestamp: Date.now(),
      metadata: metadata || undefined
    };

    // 这里可以集成更复杂的日志系统
    if (level === 'debug' && logConfig.level !== 'debug') {
      return; // 如果不是 debug 级别，跳过 debug 日志
    }
    console.log(`[${level.toUpperCase()}] ${message}`, metadata ? JSON.stringify(metadata) : '');
  }

  /**
   * 加载持久化数据
   */
  private loadPersistedData(): void {
    try {
      const data = this.dataPersistence.loadData();
      
      // 恢复设备数据
      for (const [deviceId, device] of Object.entries(data.devices)) {
        // 重置在线状态，因为服务器重启后所有设备都是离线的
        device.isOnline = false;
        this.devices.set(deviceId, device);
        // 自动补建指纹映射
        if (device.hardwareFingerprint) {
          this.fingerprintToDeviceId.set(device.hardwareFingerprint, deviceId);
        }
      }
      
      // 恢复指纹映射表（如有）
      if (data.fingerprintToDeviceId) {
        for (const [fp, id] of Object.entries(data.fingerprintToDeviceId)) {
          this.fingerprintToDeviceId.set(fp, id);
        }
      }
      this.log('info', `从持久化存储加载了 ${Object.keys(data.devices).length} 个设备`);
    } catch (error) {
      this.log('error', `加载持久化数据失败: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
  }

  /**
   * 保存持久化数据
   */
  private async savePersistedData(): Promise<void> {
    try {
      const data = {
        devices: Object.fromEntries(this.devices),
        pairings: {}, // 由 PairingManager 处理
        pairingCodes: {}, // 由 PairingManager 处理
        stats: {
          lastSave: Date.now(),
          totalDevices: this.devices.size,
          totalPairings: 0
        },
        fingerprintToDeviceId: Object.fromEntries(this.fingerprintToDeviceId) // 新增持久化
      };
      
      await this.dataPersistence.saveData(data);
    } catch (error) {
      this.log('error', `保存持久化数据失败: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
  }

  /**
   * 手动保存数据
   */
  async saveData(): Promise<void> {
    await this.savePersistedData();
  }

  /**
   * 获取数据持久化实例
   */
  getDataPersistence(): DataPersistence {
    return this.dataPersistence;
  }

  /**
   * 删除注册设备
   */
  deleteDevice(deviceId: string): boolean {
    if (!this.devices.has(deviceId)) return false;
    this.devices.delete(deviceId);
    // 清理socket映射
    for (const [socketId, dId] of this.socketToDevice.entries()) {
      if (dId === deviceId) {
        this.socketToDevice.delete(socketId);
      }
    }
    this.savePersistedData();
    this.log('info', `物理删除注册设备: ${deviceId}`);
    // 不删除指纹映射，保证永久一一对应
    return true;
  }

  /**
   * 销毁管理器
   */
  destroy(): void {
    if (this.cleanupInterval) {
      clearInterval(this.cleanupInterval);
    }
    if (this.autoSaveInterval) {
      clearInterval(this.autoSaveInterval);
    }
    if (this.dataPersistence) {
      this.dataPersistence.destroy();
    }
    this.devices.clear();
    this.socketToDevice.clear();
    this.fingerprintToDeviceId.clear(); // 销毁指纹映射
  }
}

export = DeviceManager;
